﻿using Core.FrameWork.Commons.Pages;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Core.FrameWork.Commons.ORM.UnitWork
{
    /// <summary>
    /// 工作单元接口
    /// </summary>
    public interface IUnitWork<TDbContext>
    {
        #region Insert 新增
        /// <summary>
        /// 新增实体
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        void Add<T>(T entity) where T : class;
        /// <summary>
        /// 新增实体
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        Task AddAsync<T>(T entity) where T : class;
        /// <summary>
        /// 批量新增，数量量较多是推荐使用BulkInsert()
        /// </summary>
        /// <param name="entities"></param>
        /// <returns></returns>
        void AddRange<T>(ICollection<T> entities) where T : class;
        /// <summary>
        /// 批量新增，数量量较多是推荐使用BulkInsert()
        /// </summary>
        /// <param name="entities"></param>
        /// <returns></returns>
        Task AddRangeAsync<T>(ICollection<T> entities) where T : class;

        #endregion

        #region Update 更新
        /// <summary>
        /// 更新一个实体数据
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        void Edit<T>(T entity) where T : class;
        /// <summary>
        /// 批量更新数据实体
        /// </summary>
        /// <param name="entities"></param>
        /// <returns></returns>
        void EditRange<T>(ICollection<T> entities) where T : class;
        /// <summary>
        /// 更新指定字段的值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="model">数据实体</param>
        /// <param name="updateColumns">指定字段</param>
        /// <returns></returns>
        void Update<T>(T model, params string[] updateColumns) where T : class;
        #endregion


        #region Query 查询

        IQueryable<T> Find<T>(Expression<Func<T, bool>> @where = null) where T : class;
        /// <summary>
        /// 根据条件统计数量Count()
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        int Count<T>(Expression<Func<T, bool>> @where = null) where T : class;
        /// <summary>
        /// 根据条件统计数量Count()
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        Task<int> CountAsync<T>(Expression<Func<T, bool>> @where = null) where T : class;
        /// <summary>
        /// 是否存在,存在返回true，不存在返回false
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        bool Exist<T>(Expression<Func<T, bool>> @where = null) where T : class;
        /// <summary>
        /// 是否存在,存在返回true，不存在返回false
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        Task<bool> ExistAsync<T>(Expression<Func<T, bool>> @where = null) where T : class;  
        /// <summary>
        /// 获取单个实体。建议：如需使用Include和ThenInclude请重载此方法。
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        T GetSingleOrDefault<T>(Expression<Func<T, bool>> @where) where T : class;

        /// <summary>
        /// 获取单个实体。建议：如需使用Include和ThenInclude请重载此方法。
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        Task<T> GetSingleOrDefaultAsync<T>(Expression<Func<T, bool>> @where) where T : class;
        /// <summary>
        /// 获取实体列表。建议：如需使用Include和ThenInclude请重载此方法。
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        IList<T> Get<T>(Expression<Func<T, bool>> @where) where T : class;

        /// <summary>
        /// 获取实体列表。建议：如需使用Include和ThenInclude请重载此方法。
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        Task<IList<T>> GetAsync<T>(Expression<Func<T, bool>> @where) where T : class;
        /// <summary>
        /// 获取实体列表。建议：如需使用Include和ThenInclude请重载此方法。
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        IList<T> Get<T>(Expression<Func<T, bool>> @where, bool[] asc, params Expression<Func<T, object>>[] @orderby) where T : class;

        /// <summary>
        /// 获取实体列表。建议：如需使用Include和ThenInclude请重载此方法。
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        Task<IList<T>> GetAsync<T>(Expression<Func<T, bool>> @where, bool[] asc, params Expression<Func<T, object>>[] @orderby) where T : class;
        /// <summary>
        ///  分页获取实体列表。建议：如需使用Include和ThenInclude请重载此方法。
        /// </summary>
        /// <param name="where">查询条件</param>
        /// <param name="pagerInfo">分页信息</param>
        /// <param name="asc">排序方式</param>
        /// <param name="orderby">排序字段</param>
        /// <returns></returns>
        IEnumerable<T> GetByPagination<T>(Expression<Func<T, bool>> @where, PagerInfo pagerInfo, bool[] asc,
            params Expression<Func<T, object>>[] @orderby) where T : class;
        /// <summary>
        ///  分页获取实体列表。建议：如需使用Include和ThenInclude请重载此方法。
        /// </summary>
        /// <param name="where">查询条件</param>
        /// <param name="pagerInfo">分页信息</param>
        /// <param name="asc">排序方式</param>
        /// <param name="orderby">排序字段</param>
        /// <returns></returns>
        Task<IList<T>> GetByPaginationAsync<T>(Expression<Func<T, bool>> @where, PagerInfo pagerInfo, bool[] asc,
            params Expression<Func<T, object>>[] @orderby) where T : class;
        /// <summary>
        /// sql语句查询数据集
        /// </summary>
        /// <param name="sql"></param>
        /// <returns></returns>
        List<T> GetBySql<T>(string sql) where T : class;
        /// <summary>
        /// sql语句查询数据集，返回输出Dto实体
        /// </summary>
        /// <typeparam name="TView">返回结果对象</typeparam>
        /// <param name="sql"></param>
        /// <returns></returns>
        List<TView> GetViews<T,TView>(string sql) where T : class;
        /// <summary>
        /// 查询视图
        /// </summary>
        /// <typeparam name="TView">返回结果对象</typeparam>
        /// <param name="viewName">视图名称</param>
        /// <param name="where">查询条件</param>
        /// <returns></returns>
        List<TView> GetViews<T,TView>(string viewName, Func<TView, bool> where) where T : class;

        #endregion
        int Save();
        Task<int> SaveAsync();
    }
}
